
//#include <winsock2.h>
//#include <windows.h>

extern "C" int getch();

#include <iostream>
using namespace std;


#include "GProcessor.h"
#include "GFunction.h"
#include "GUtility.h"

using namespace GMachine;


struct TestPoint
{
	int x; 
	int y;
};

/*
<xs:element name="number" type="xs:double"></xs:element>
<xs:element name="string" type="xs:string"></xs:element>

xsd + xml + mparser = xsc
xsd + xcc = xparser
xsc + xparser = gmidl
*/

float Testcase0(bool a, unsigned char b, signed char c, unsigned short d, signed short e, unsigned long int f, signed long int g)
{
	cout<<"a="<<a<<", b="<<b<<", c="<<c<<", d="<<d<<", e="<<e<<", f="<<f<<", g="<<g<<endl;
	return 0.001f;
}

double Testcase1(char a, unsigned char b, signed char c, unsigned short d, signed short e, unsigned long int f, signed long int g)
{
	cout<<"a="<<a<<", b="<<b<<", c="<<c<<", d="<<d<<", e="<<e<<", f="<<f<<", g="<<g<<endl;
	return 0.001;
}

//float Testcase2(unsigned long long int a, signed long long int b, float c, double d)
//{
//	cout<<"a="<<a<<", b="<<b<<", c="<<c<<", d="<<d<<endl;		
//	return 2;
//}

float Testcase3(void * a, char * b, TestPoint * c)
{
	printf("a = %p, b = %p, c = %p\n", a, b, c);
	return -3;
}

float Testcase4(void * a, const char * b, const TestPoint * c)
{
	printf("a = %p, b = %p, c = %p\n", a, b, c);
	printf("a = %p, b = \"%s\", c->x = %d, c->y = %d\n", a, b, c->x, c->y);
	return 4;
}

float Testcase5(void * a, const char * b, TestPoint& c)
{
	printf("a = %p, b = %p, c = %p\n", a, b, c);
	printf("a = %p, b = \"%s\", c.x = %d, c.y = %d\n", a, b, c.x, c.y);
	return 5.55f;
}


float Testcase6(int& a, float& b, const char *& c)
{	
	printf("a = %d, b = %lf, c = %s\n", a, b, c);
	return 6.66f;
}


int& Testcase7(int& var)
{
	var++;
	return var;
}

void noarg()
{
	printf("hahaha\n");
	//return 0;
}

int test()
{
	GProcessor prc;

	//*
	FunctionObject obj = ExportFunction(&noarg);	
	prc.stk.PushReg(Regname::G0);
	prc.stk.PushVal(IntegerObject('a'));
#	define COUNT	10
#	define PRINTRET 
#	define TESTING  1.0f
	//*/


	/*
	FunctionObject obj = ExportFunction(&Testcase0);
	prc.stk.PushReg(Regname::F0);
	prc.stk.PushVal(IntegerObject('a'));
	prc.stk.PushVal(IntegerObject('b'));
	prc.stk.PushVal(IntegerObject('c'));
	prc.stk.PushVal(IntegerObject(40));
	prc.stk.PushVal(IntegerObject(-50));
	prc.stk.PushVal(IntegerObject(60));
	prc.stk.PushVal(IntegerObject(-70));
#	define COUNT	10
#	define PRINTRET 
#	define TESTING  Testcase0(true, 'b', 'c', 40, -50, 60, -70)
	//*/

	/*
	FunctionObject obj = ExportFunction(&Testcase1);
	prc.stk.PushReg(Regname::F0);
	prc.stk.PushVal(IntegerObject('a'));
	prc.stk.PushVal(IntegerObject('b'));
	prc.stk.PushVal(IntegerObject('c'));
	prc.stk.PushVal(IntegerObject(40));
	prc.stk.PushVal(IntegerObject(-50));
	prc.stk.PushVal(IntegerObject(60));
	prc.stk.PushVal(IntegerObject(-70));
#	define COUNT	10
#	define PRINTRET 
#	define TESTING  Testcase1('a', 'b', 'c', 40, -50, 60, -70)
	//*/

	/*
	FunctionObject obj = ExportFunction(&Testcase2);
	prc.stk.PushReg(Regname::F0);
	prc.stk.PushVal(IntegerObject(1000));
	prc.stk.PushVal(IntegerObject(2000));	
	prc.stk.PushVal(FloatingObject(3333.3333));
	prc.stk.PushVal(FloatingObject(4444.4444));
#	define COUNT	5
#	define PRINTRET 
#	define TESTING  Testcase2(1000, 2000, 3333.3333f, 4444.4444)
	//*/

	/*
	FunctionObject obj = ExportFunction(&Testcase3);
	prc.stk.PushReg(Regname::F0);
	void * pt = (void*)(0x10);
	prc.reg.H[0] = &pt;
	prc.stk.PushReg(Regname::H0);
	char str[] = "This is a test.";
	prc.reg.H[1] = str;
	prc.stk.PushReg(Regname::H1);
	TestPoint tp = {100, 200};
	prc.reg.H[2] = &tp;
	prc.stk.PushReg(Regname::H2);
#	define COUNT	5
#	define PRINTRET 
#	define TESTING Testcase3(&pt, str, &tp)
	//*/

	
	/*
	FunctionObject obj = ExportFunction(&Testcase4);
	prc.stk.PushReg(Regname::F0);
	void * pt = (void*)(0x10);
	prc.reg.H[0] = &pt;
	prc.stk.PushReg(Regname::H0);
	char str[] = "This is a test.";
	prc.reg.H[1] = str;
	prc.stk.PushReg(Regname::H1);
	TestPoint tp = {900, 800};
	prc.reg.H[2] = &tp;
	prc.stk.PushReg(Regname::H2);
#	define COUNT	5
#	define PRINTRET 
#	define TESTING Testcase4(&pt, str, &tp)
	//*/

	/*
	FunctionObject obj = ExportFunction(&Testcase5);
	prc.stk.PushReg(Regname::F0);
	void * pt = (void*)(0x10);
	prc.reg.H[0] = &pt;
	prc.stk.PushReg(Regname::H0);
	char str[] = "This is a test.";
	prc.reg.H[1] = str;
	prc.stk.PushReg(Regname::H1);
	TestPoint tp = {100, 200};
	prc.reg.H[2] = &tp;
	prc.stk.PushReg(Regname::H2);
#	define COUNT	5
#	define PRINTRET 
#	define TESTING Testcase5(&pt, str, tp)
	//*/

	/*
	FunctionObject obj = ExportFunction(&Testcase6);
	prc.stk.PushReg(Regname::F0);
	int va = 100;
	prc.reg.H[0] = &va;
	prc.stk.PushReg(Regname::H0);
	float vb = 222.22f;
	prc.reg.H[1] = &vb;
	prc.stk.PushReg(Regname::H1);
	const char * vc = "hahaha, successful?";
	prc.reg.H[2] = (HandleObject)(&vc);
	prc.stk.PushReg(Regname::H2);
#	define COUNT	5
#	define PRINTRET 
#	define TESTING Testcase6(va, vb, vc)
	//*/

	/*
	FunctionObject obj = ExportFunction(&Testcase7);	
	int va = 100;
	prc.reg.H[0] = &va;
	int vb = 50000;
	prc.reg.H[1] = &vb;
	prc.stk.PushReg(Regname::H1);
	prc.stk.PushReg(Regname::H0);
#	define COUNT	5
#	define PRINTRET printf("script retval: %d\n", *(int*)(prc.reg.H[0]))
#	define TESTING printf("cpp retval:%d\n", Testcase7(va));
	//*/

	
	//*
	//==========================================================
	obj.Invoke(prc.stk, prc.reg);
	PRINTRET;
	printf("--------------------------------\n");
	TESTING;


	printf("1st: %lf\n", prc.reg.F[0]);
	printf("2nd: %lf\n", TESTING);
	//==========================================================
	//*/
	return 0;
}




//FormatParam<int, long, long, long float> params(info, bytes);
//param.data, param.next.data, param.next.data;



/*

template<typename T, unsigned int cellid>
struct ParamFormat
{
	Conversion::Check<IntegerClass, T>::Exist : cellid = GCELL;
	Conversion::Check<FloatingClass, T>::Exist : cellid = FCELL:
};
*/

//Script->C++:
/*




IntegerClass -> ...

FloatingClass -> ...
IntegerClass[2], IntegerClass[4], IntegerClass[8], IntegerClass[16], IntegerClass[32] -> ...
FloatingClass[2], FloatingClass[4], FloatingClass[8], FloatingClass[16], FloatingClass[32] -> ...
*/

//C++->Script
/*
struct Point
{
	int x;
	int y;
};

...->IntegerClass
...->FloatingClass
...->IntegerClass[2], IntegerClass[4], IntegerClass[8], IntegerClass[16], IntegerClass[32]
...->FloatingClass[2], FloatingClass[4], FloatingClass[8], FloatingClass[16], FloatingClass[32]

template<typename T>
struct CPPConv
{
}

template<>
struct CPPConv<IntegerClass>
{
}

template<>
struct CPPConv<FloatingClass>
{
}

template<>
struct CPPConv<StringClass>
{
}

*/
/*
template<typename TRET, typename P1, typename P2>
struct Unbox
{
	Unbox(char[3] cellinfo, void * stacker,)
	{

		

		
	}
};
*/
/*

FormatParam<P1, P2, P3, P4>
{
	unitsize[4];
	P1 * p1;
	P2 * p2;
	P3 * p3;
	P4 * p4;
	FormatParam(U8 * data, U8 * info, unsigned int count)
	{
		if (count >= 4)
		{
			switch(*info)
			{
			case GCELL:
       			p1 = data;				
				break;
			case FCELL:
				p1 = data;
				break;
			case RCELL:
				p1 = GetRegReference(*data);
				break;
			}

			data += unisize[*info]; info++;
		}
	}
	

}

int main()
{
	
	char * buffer = new char[1024 * 1024 * 200];

	memset(buffer, 0, 1024 * 1024 * 200);

	GProcessor processor;

	unsigned long time = GetTickCount();
	processor.Process(buffer, 1024 * 1024 * 200);
	cout<<GetTickCount() - time<<"ms"<<endl;;

	delete[] buffer;
	
	return 0;
}
*/

/*
integerStack.append	integer(899100)	//int
integerStack.append integer(10)		//char
floatStack.append	float(219.78)		//float
call MyFunc4
pop integerStack

==>
move G0, 899100
move G1, 10
move F0, 219.78
pare G2
call MyFunc4



1
2 call
3


push_g 4, 887182
push_f 4, 1288.82
push_s 8, "12345678"




[push_g][4][][][][][push_f][][][][][push_s][8][][][][][][][][]					21B

type_g
push 4, 887182
type_f
push 4, 1288.82
type_s
push 8, "12345678"

[load_4][regid][][][][][load_4][regid][][][][][load_8][regid][][][][][][][][]	22B		ok

load_(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768)



load_2 G0, 887283		G0 = 887283
load_2 G1, 102398		G1 = 102398
inc G0, G1				G0 = 887283 + 102398
add G2, G0, G1			G2 = 887283 + 102398 + 102398
[load_2][G0][][][][][load_2][G1][][][][][inc][G0][G1][add][G2][G0][G1]	19B				ok

load_2 G0, 887283		G0 = 887283
inc G0, 102398			G0 = 887283 + 102398
add G2, G0, 102398		G2 = 887283 + 102398 + 10298
[load_2][G0][][][][][inc][G0][][][][][add][G2][G0][][][][]				19B


load_4 G0, 1212
load_4 G1, 34121
load_4 G2, 768268
load_4 G3, 384
param_4 G0, G1, G2, G3 
call func_with4param

[load_4][G0][][][][][load_4][G1][][][][][load_4][G2][][][][][load_4][G3][][][][][param_4][][][][][call][][][][]	34B

push_g4 1212
push_g4 34121
push_g4 768268
push_g4 384
call func_with4param
[push_g4][][][][][push_g4][][][][][push_g4][][][][][push_g4][][][][][call][][][][]								25B






load reg, val
load_1, load_2, load_4, load_8, 
load_16, load_32, load_64, load_128, 
load_256, 

load_r reg, hreg


push_x val
push_r reg

push_4, push_8, 
push_16, push_32, push_64, push_128
push_256, push_512, push_1024, push_2048
push_4096, push_8192, push_16384, push_32768




[load_x1][][0...256]
[load_x2][][][0...65536]
[load_x4][][][][][0...2^32]




loadoffset	reg, S/H
loadoffset_x1
loadoffset_x2
loadoffset_x4

initzero	G/F/S/H
loadunit_1	G/F, val
loadunit_2
loadunit_3
loadunit_4
loadunit_5
loadunit_6
loadunit_7
loadunit_8
loadpack_x1	S/H, val
loadpack_x2	
loadpack_x4	

pushi_g
pushi_f
pushg
pushf
pushr	reg


add
sub
div
mul
pow
log
sin
cos
tan
sum
ave


*/



